<?php

defined('__MAPEXEC__') or die('No direct access allowed');

class Maps_Geocode_Yahoo extends Maps_Geocode_Common {
  
  /**
   * Extracts the latitude and longitude from the lookup response.
   * @param   array         Array of geographic information
   * @return  Maps_LatLng   Latitude and longitude object
   */
  protected function extractCoords($geoData) {
    $lat = (double) $geoData['ResultSet']['Result']['Latitude'];
    $lng = (double) $geoData['ResultSet']['Result']['Longitude'];
    
    if ( !empty($lat) && !empty($lng) ) {
      return new Maps_LatLng($lat, $lng);
    } else {
      return null;
    }
  }
  
  /**
   * Gets the geocoding data from the Yahoo.
   * @param   string  URI to send geocoding request to.
   * @return  mixed   Array when successfull, false when not.
   */
  private function getGeoData($uri) {
    $latlng = null;
    
    try {
      $response = file_get_contents($uri);
      try {
        $geoData = unserialize($response);
        $latlng = $this->extractCoords($geoData);
      } catch (Exception $e) {
        try {
          // Daily API call limit exceeded
          $xml = simplexml_load_string($response);
          die('Geocoding error: ' . $xml->Error->Message);
        } catch (Exception $e) {
          // Bad response
          $latlng = null;
        }
      }
    } catch (Exception $e) {
      // Bad address
      $latlng = null;
    }
    
    return $latlng;
  }
  
  /**
   * Looks up the geo coordinates of an address. Takes the same arguments as the constructor
   * for Maps_Geo_Location. Yahoo Maps Geocoding API is currently limited to the United
   * States or America. Any non US address will return a null value.
   * @param   Maps_Geocode_Location   Location object
   * @return  array                   Associative array of lat and lng coordinates.
   */
  protected function lookup(Maps_Geocode_Location $location) {
    if ($location->getCountry() == "US") {
      $uri = 'http://local.yahooapis.com/MapsService/V1/geocode?output=php&appid=' . $this->getAPIKey() .
          '&street=' . rawurlencode($location->getAddress()) .
          '&city=' . rawurlencode($location->getCity()) .
          '&state=' . rawurlencode($location->getRegion()) .
          '&zip=' . rawurlencode($location->getPostalCode());
      
      return $this->getGeoData($uri);
    } else {
      return null;
    }
  }
  
}

?>